#pragma once 
#include <vector>
#include <semaphore.h>
#include "Task.hpp"
#include "LockGuard.hpp"

namespace wyl
{
    #define DEFAULT_NUM 5
    template<class T>
    class RingQueue
    {
    private:
        unsigned int _num; 
        std::vector<T> _ring_queue; 
        unsigned int _con_idx; 
        unsigned int _prod_idx;
        sem_t _space_sem; //生产者关注空间
        sem_t _data_sem; //消费者关注数据
        pthread_mutex_t _clock; //维护消费者与消费者之间的互斥关系的锁
        pthread_mutex_t _plock; //维护生产者与生产者之间互斥关系的锁

    public:
        RingQueue(unsigned int num = DEFAULT_NUM) : _num(num ) , _ring_queue(num),
            _con_idx(0),_prod_idx(0)
        {
            sem_init(&_space_sem,0,_num); //初始化信号量
            sem_init(&_data_sem,0,0);
        }
        ~RingQueue()
        {
            sem_destroy(&_space_sem);
            sem_destroy(&_data_sem);
        }
    
    public:
        void Pop(T* out)
        {
            sem_wait(&_data_sem) ; //数据--
            pthread_mutex_lock(&_clock);
            *out = _ring_queue[_con_idx++];
            _con_idx %= _num;  //消费者向后走
            pthread_mutex_unlock(&_clock);
            sem_post(&_space_sem); //空间++ 
        }
        void Push(const T& in)
        {
            sem_wait(&_space_sem) ; //空间-- 
            pthread_mutex_lock(&_plock);
            _ring_queue[_prod_idx++] = in;
            _prod_idx %= _num;  //生产者向后走
            pthread_mutex_unlock(&_plock);
            sem_post(&_data_sem); //数据++
        }
    };
};